﻿using Common;
using CommonModel;
using IBll;
using System.Collections.Generic;

namespace Bll
{
    /// <summary>
    /// 通用服务服务
    /// </summary>
    public class CommonServiceBll : ICommonServiceBll
    {
        public ICacheBll CacheBll { get; set; }

        /// <summary>
        /// 通用服务组件集合（IIS应用程序池会间隔时长自动回收静态变量）
        /// </summary>
        private static Dictionary<string, List<ICommonService>> CommonServiceList { get; set; }
        private static readonly object LockHelper = new object();

        /// <summary>
        /// 执行服务
        /// </summary>
        /// <param name="param"></param>
        /// <param name="response"></param>
        /// <returns></returns>
        public bool ExecuteService(dynamic param, out string response)
        {
            bool result = false;
            response = "";
            string serviceCode = param.ServiceCode;

            #region 方案一（不可用，因为redis取对象缓存时，会根据类的命名空间全路径来实例化。但是通过dll组件方式动态加载，是超出系统的命名空间范围的。未验证，但是不可用多半是这种原因。）
            //List<ICommonService> commonServiceList = GetCommonServiceList(serviceCode);
            //if (commonServiceList != null && commonServiceList.Count > 0)
            //{
            //    LogHelper.Debug("服务编码为" + serviceCode + "的组件dll数量为：" + commonServiceList.Count);
            //    for (int i = 0; i < commonServiceList.Count; i++)
            //    {
            //        LogHelper.Debug("服务编码为" + serviceCode + "的第" + (i + 1) + "个组件开始执行");
            //        if (commonServiceList[i].ExecuteService(param, out response))
            //        {
            //            LogHelper.Debug("服务编码为" + serviceCode + "的第" + (i + 1) + "个组件执行返回成功");
            //            result = true;
            //            break;
            //        }
            //        else
            //        {
            //            LogHelper.Debug("服务编码为" + serviceCode + "的第" + (i + 1) + "个组件执行返回失败");
            //        }
            //    }
            //}
            //else
            //{
            //    LogHelper.Debug("不存在服务编码为" + serviceCode + "的组件dll");
            //}
            #endregion

            #region 方案二
            LoadCommonServiceList(serviceCode);
            if (CommonServiceList.ContainsKey(serviceCode) && CommonServiceList[serviceCode].Count > 0)
            {
                LogHelper.Debug("服务编码为" + serviceCode + "的组件数量为：" + CommonServiceList[serviceCode].Count);
                for (int i = 0; i < CommonServiceList[serviceCode].Count; i++)
                {
                    LogHelper.Debug("服务编码为" + serviceCode + "的第" + (i + 1) + "个组件开始执行");
                    if (CommonServiceList[serviceCode][i].ExecuteService(param, out response))
                    {
                        LogHelper.Debug("服务编码为" + serviceCode + "的第" + (i + 1) + "个组件执行返回成功");
                        result = true;
                        break;
                    }
                    else
                    {
                        LogHelper.Debug("服务编码为" + serviceCode + "的第" + (i + 1) + "个组件执行返回失败");
                    }
                }
            }
            else
            {
                LogHelper.Debug("不存在服务编码为" + serviceCode + "的组件");
            }
            #endregion

            return result;
        }

        /// <summary>
        /// 重加载服务
        /// </summary>
        /// <param name="serviceCode"></param>
        /// <returns></returns>
        public bool ReloadService(string serviceCode)
        {
            bool result = false;

            if (CommonServiceList == null)
            {
                LoadCommonServiceList(serviceCode);
                result = true;
            }
            else
            {
                if (CommonServiceList.Remove(serviceCode))
                {
                    LoadCommonServiceList(serviceCode);
                    result = true;
                }
            }


            return result;
        }

        #region 私有方法
        /// <summary>
        /// 加载通用服务组件集合
        /// </summary>
        /// <param name="serviceCode"></param>
        private void LoadCommonServiceList(string serviceCode)
        {
            lock (LockHelper)//静态成员的初始化，只需要一个线程去操作即可，减少不必要的操作
            {
                if (CommonServiceList == null)
                {
                    CommonServiceList = new Dictionary<string, List<ICommonService>>();
                }
                if (!CommonServiceList.ContainsKey(serviceCode))
                {
                    List<ICommonService> commonServiceListCurrentServiceCode = new FactoryHelper($@"CommonServiceDll\{serviceCode}", $"CommonService.{serviceCode}.*.dll").Produce<ICommonService>();
                    if (commonServiceListCurrentServiceCode.Count > 0)
                    {
                        LogHelper.Debug("首次加载" + serviceCode + "组件");
                        CommonServiceList.Add(serviceCode, commonServiceListCurrentServiceCode);
                    }
                }
            }
            //不建议使用如下操作进行服务组件的重加载，建议统一使用ReloadServiceWithCode服务
            //int dllCount = Directory.GetFiles(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, $@"CommonServiceDll\{serviceCode}"), $"CommonService.{serviceCode}.*.dll").Length;
            //if (CommonServiceList[serviceCode].Count != dllCount) //粗略判断：内存中组件实例和组件数不一致则认为有更新
            //{
            //    LogHelper.Debug(serviceCode + "组件有更新，重新加载");
            //    List<ICommonService> commonServiceListCurrentServiceCode = new PluginManager($@"CommonServiceDll\{serviceCode}", $"CommonService.{serviceCode}.*.dll").GetPlugin<ICommonService>();
            //    CommonServiceList[serviceCode] = commonServiceListCurrentServiceCode;
            //}
        }
        /// <summary>
        /// 获取通用服务接口实例集合
        /// </summary>
        /// <param name="serviceCode"></param>
        /// <returns></returns>
        //private List<ICommonService> GetCommonServiceList(string serviceCode)
        //{
        //    List<ICommonService> result = null;

        //    if (!CacheBll.IsExists(serviceCode))
        //    {
        //        LogHelper.Debug("首次加载组件");
        //        result = new PluginManager($@"CommonServiceDll\{serviceCode}", $"CommonService.{serviceCode}.*.dll").GetPlugin<ICommonService>();
        //        CacheBll.Add(serviceCode, result);
        //    }
        //    else
        //    {
        //        List<ICommonService> commonServiceList = CacheBll.GetCache<List<ICommonService>>(serviceCode);
        //        int dllCount = Directory.GetFiles(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, $@"CommonServiceDll\{serviceCode}"), $"CommonService.{serviceCode}.*.dll").Length;
        //        if (commonServiceList.Count != dllCount)//粗略判断：内存中组件实例和组件数不一致则认为有更新
        //        {
        //            LogHelper.Debug("组件有更新，重新加载");
        //            result = new PluginManager($@"CommonServiceDll\{serviceCode}", $"CommonService.{serviceCode}.*.dll").GetPlugin<ICommonService>();
        //            CacheBll.Update(serviceCode, result);
        //        }
        //        else
        //        {
        //            result = commonServiceList;
        //        }
        //    }

        //    return result;
        //}
        #endregion
    }
}
